#pragma once
#ifndef MYSLAM_MAPPOINT_H
#define MYSLAM_MAPPOINT_H

#include "myslam/common_include.h"

namespace myslam{

    struct Frame; //这里为什么要声明Frame？应该是可有可无的
    struct Feature;

/**
 * 路标点类
 * 特征点在三角化之后形成路标点
 */
    struct MapPoint{
        public:
                EIGEN_MAKE_ALIGNED_OPERATOR_NEW;

        typedef std::shared_ptr<MapPoint> Ptr;
        unsigned long id_ = 0;   // 路标点id
        bool is_outlier_ = false;   // 是否是异常点
        Vec3 pos_ = Vec3::Zero();  // 路标点世界坐标，初始值为0

        std::mutex data_mutex_;
        int observed_times_ = 0;  // 记录这个路标点被关键帧观察（提取）到的次数

        // 用链表储存观测到这个路标点的所有特征点（关键帧）
        std::list<std::weak_ptr<Feature>> observations_;

        MapPoint() {}

        MapPoint(long id, Vec3 position);

       // 取、改路标点，前后端都访问，上锁
        Vec3 Pos() {
            std::unique_lock<std::mutex> lck(data_mutex_);
            return pos_;
        }

        void SetPos(const Vec3 &pos) {
            std::unique_lock<std::mutex> lck(data_mutex_);
            pos_ = pos;
        };

        // 增加新的观测到这个路标点，并且特征点数量+1
        void AddObservation(std::shared_ptr<Feature> feature) {
            std::unique_lock<std::mutex> lck(data_mutex_);
            observations_.push_back(feature);
            observed_times_++;
        }

         // 可能是异常点，也可能将要删除某个关键帧，所以要移除某个特征点，并且特征点数量-1
        void RemoveObservation(std::shared_ptr<Feature> feat);

         // 取出特征点存储的链表
        std::list<std::weak_ptr<Feature>> GetObs() {
            std::unique_lock<std::mutex> lck(data_mutex_);
            return observations_;
        }

        // factory function
        static MapPoint::Ptr CreateNewMappoint();
    };
}

#endif  // MYSLAM_MAPPOINT_H
